#include "../Tools/GLHeaders.hpp" 
#include "DisplayFunc.hpp"

#include <cmath>
#include <cstring>
#include "../Global.hpp"
#include "../Tools/Chrono.hpp"
#include "../Tools/Background.hpp"
#include "../Tools/Foreground.hpp"
#include "../Tools/ReferenceCube.hpp"
#include "../Tools/ReferenceFrame.hpp"
#include "../Face/Face.hpp"

GLuint text_glow; // id glow Texture
GLuint EmptyTexture(GLsizei with, GLsizei height, GLint format);
void RenderToTexture(GLsizei width, GLsizei height);
void RenderGlow(GLint nb_pass, GLsizei width, GLsizei height);

void DrawGLScene(void){
  static GLsizei width = window.width;
  static GLsizei height = window.height;
  static Chrono time;
  static bool init = false;
  GLfloat temp;

  if(!init){
    text_glow = EmptyTexture(width, height, 4);
    time.Reset();
    time.Activate();
    init = true;
  }
  if(width != window.width || height != window.height){
    glDeleteTextures(1, &text_glow);
    width = window.width;
    height = window.height;
    text_glow = EmptyTexture(width, height, 4);
  }
  temp = time.GetTime();
  // Draw Glow scene
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
  glTranslatef(0.0f, 0.0f, -4.0f);
  glRotatef(50*time.GetTime(), 0.0f, 1.0f, 0.0f);

  Background.Draw();
  ReferenceFrame.Draw();
  glScalef(1.0f-fabsf(cosf(temp)/1.5f), 1.0f-fabsf(cosf(temp)/1.5f), 1.0f-fabsf(cosf(temp)/1.5f));
  ReferenceCube.Draw();
  //face.Draw();
  RenderToTexture(window.width, window.height);
 
 // Draw the Real scene
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
  glRotatef(-50*temp, 0.0f, 0.0f, 1.0f);
  glTranslatef(2.0f, 0.0f, -6.0f);
  glRotatef(50*temp, 1.0f, 1.0f, 1.0f);
  
  Background.Draw();
  ReferenceCube.Draw();
  RenderGlow(20, window.width, window.height);
  //Foreground.Draw();

  glutSwapBuffers();
}

GLuint EmptyTexture(GLsizei width, GLsizei height, GLint format){
  GLuint result;
  GLubyte *data;

  data = (GLubyte*)new GLubyte[((width * height)* format * sizeof(GLubyte))];
  memset((void *)data, 0x00, width*height*format*sizeof(GLubyte));
  glGenTextures(1, &result);
  glPushAttrib(GL_TEXTURE_BIT);
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, result);
  glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

  delete [] data;
  glPopAttrib();
  return result;
}

void RenderToTexture(GLsizei width, GLsizei height){
  glPushAttrib(GL_TEXTURE_BIT);
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, text_glow); 
  //glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, width, height, 0);
  glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height); 
  glPopAttrib();  
}

void RenderGlow(GLint nb_pass, GLsizei width, GLsizei height){
  glPushAttrib(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_TEXTURE_BIT);
  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  glOrtho(0, width , 0, height, -1.0f, 1.0f);

  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glLoadIdentity();

  glEnable(GL_TEXTURE_2D);	
  glBindTexture(GL_TEXTURE_2D,text_glow);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDisable(GL_DEPTH_TEST);

  glBegin(GL_QUADS);
  GLfloat temp;
  for (int i=0; i< nb_pass; i++) {
    temp = (GLfloat)i/85.0f;
    glColor4f(1.0f, 1.0f, 1.0f, 0.3f/(GLfloat)i);  
    glTexCoord2f(0+temp,0+temp); glVertex2f(0.0f,0.0f);
    glTexCoord2f(1-temp,0+temp); glVertex2f(width,0.0f);
    glTexCoord2f(1-temp,1-temp); glVertex2f(width, height);
    glTexCoord2f(0+temp,1-temp); glVertex2f(0.0f, height);
  }
  glEnd();

  // On repasse en vision en perspective 
  glMatrixMode( GL_PROJECTION );
  glPopMatrix();
  glMatrixMode( GL_MODELVIEW );
  glPopMatrix();
  glPopAttrib();
}
